/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * main.c
 * Copyright (C) Kevin DeKorte 2009 <kdekorte@gmail.com>
 * 
 * MediaWall is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * MediaWall is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#include <config.h>

#include <gtk/gtk.h>
#include <clutter/clutter.h>
#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <clutter-gtk/clutter-gtk.h>
#include <clutter-gst/clutter-gst.h>



/*
 * Standard gettext macros.
 */
/*
#ifdef ENABLE_NLS
#  include <libintl.h>
#  undef _
#  define _(String) dgettext (PACKAGE, String)
#  ifdef gettext_noop
#    define N_(String) gettext_noop (String)
#  else
#    define N_(String) (String)
#  endif
#else
#  define textdomain(String) (String)
#  define gettext(String) (String)
#  define dgettext(Domain,Message) (Message)
#  define dcgettext(Domain,Message,Type) (Message)
#  define bindtextdomain(Domain,Directory) (Domain)
#  define _(String) (String)
#  define N_(String) (String)
#endif
*/

#include "callbacks.h"
#include "dbus-interface.h"
#include "fosfor.h"
#include "declarations.h"

#include "fosfor_button.h"
#include "fosfor_tracker.h"
#include "fosfor_volume.h"


static GOptionEntry entries[] = {
    {"window", 0, 0, G_OPTION_ARG_INT, &embed_window, N_("Window to embed in"), "WID"},
    {"width", 'w', 0, G_OPTION_ARG_INT, &window_width, N_("Width of window to embed in"), "X"},
    {"height", 'h', 0, G_OPTION_ARG_INT, &window_height, N_("Height of window to embed in"), "Y"},
    {"controlid", 0, 0, G_OPTION_ARG_INT, &control_id, N_("Unique DBUS controller id"), "CID"},
    {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, N_("Show more output on the console"), NULL},
	{"showcontrols", 0, 0, G_OPTION_ARG_INT, &showcontrols, N_("Show the controls in window"), "[0|1]"},
    {"autostart", 0, 0, G_OPTION_ARG_INT, &autostart, N_("Autostart the media default to 1, set to 0 to load but don't play"), "[0|1]"},
    {"rpname", 0, 0, G_OPTION_ARG_STRING, &rpname, N_("Real Player Name"), "NAME"},
	{"disablecontextmenu", 0, 0, G_OPTION_ARG_NONE, &disable_context_menu, N_("Disable popup menu on right click"), NULL},
	{NULL}
};


GtkWidget*
create_window (gint embed_window)
{
	GtkBuilder *builder;
	GError* error = NULL;
    GstBus *bus;
    GtkVBox *vbox;
	GtkTargetEntry target_entry[3];
	gint i = 0;
	GtkRecentManager *recent_manager;
	GtkRecentFilter *recent_filter;
	GList *icon_list;
	GdkPixbuf *pb_icon;
	GtkIconTheme *icon_theme;
	gdouble value;
	
	ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xFF };

	builder = gtk_builder_new ();
	if (!gtk_builder_add_from_string (builder, fosfor_ui, -1, &error))
	{
		g_warning ("Couldn't load builder file: %s", error->message);
		g_error_free (error);
	}

    /* Create the window and some child widgets: */
    window = GTK_WIDGET(gtk_builder_get_object(builder,"window"));
	if (embed_window > 0) {
        gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
        GTK_WIDGET_SET_FLAGS(window, GTK_CAN_FOCUS);
    }	
    gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE);
    //gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);
    gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
    gtk_widget_add_events(window, GDK_BUTTON_RELEASE_MASK);
    gtk_widget_add_events(window, GDK_KEY_PRESS_MASK);
    gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK);
    gtk_widget_add_events(window, GDK_ENTER_NOTIFY_MASK);
    gtk_widget_add_events(window, GDK_LEAVE_NOTIFY_MASK);
    gtk_widget_add_events(window, GDK_KEY_PRESS_MASK);
    gtk_widget_add_events(window, GDK_VISIBILITY_NOTIFY_MASK);
    gtk_widget_add_events(window, GDK_STRUCTURE_MASK);
    gtk_widget_add_events(window, GDK_POINTER_MOTION_MASK);

	target_entry[i].target = DRAG_NAME_0;
    target_entry[i].flags = 0;
    target_entry[i++].info = DRAG_INFO_0;
    target_entry[i].target = DRAG_NAME_1;
    target_entry[i].flags = 0;
    target_entry[i++].info = DRAG_INFO_1;
    target_entry[i].target = DRAG_NAME_2;
    target_entry[i].flags = 0;
    target_entry[i++].info = DRAG_INFO_2;

    gtk_drag_dest_set(window,
                      GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT |
                      GTK_DEST_DEFAULT_DROP, target_entry, i, GDK_ACTION_LINK);
    gtk_drag_dest_add_uri_targets(window);


	
	g_signal_connect(window,"delete-event", G_CALLBACK(on_window_delete_event), NULL); 
    vbox = GTK_VBOX(gtk_builder_get_object(builder,"vbox1"));
    main_menu = GTK_WIDGET(gtk_builder_get_object(builder,"main_menu"));
    fixed = GTK_FIXED(gtk_builder_get_object(builder,"fixed"));

    menuitem_file = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_file"));
    menu_file = GTK_WIDGET(gtk_builder_get_object(builder,"menu_file"));
	menuitem_file_open_recent = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_file_open_recent"));
	menuitem_file_details = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_file_details"));

	menuitem_select = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_select"));
	menuitem_select_audio = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_select_audio"));
	menuitem_select_subtitle = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_select_subtitle"));
	
	menu_select = GTK_WIDGET(gtk_builder_get_object(builder,"menu_select"));
	menu_subtitles = NULL;
	menu_languages = NULL;

    menuitem_view = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view"));
    menu_view = GTK_WIDGET(gtk_builder_get_object(builder,"menu_view"));
    menuitem_view_fullscreen = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_fullscreen"));
    menuitem_view_controls = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_controls"));
	
    menuitem_view_aspect_default = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_aspect_default"));
    menuitem_view_aspect_16x9 = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_aspect_16x9"));
    menuitem_view_aspect_16x10 = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_aspect_16x10"));
    menuitem_view_aspect_4x3 = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_aspect_4x3"));
    menuitem_view_aspect_follow = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_view_aspect_follow"));

    menuitem_help = GTK_WIDGET(gtk_builder_get_object(builder,"menuitem_help"));
    menu_help = GTK_WIDGET(gtk_builder_get_object(builder,"menu_help"));
	
	recent_manager = gtk_recent_manager_get_default();
	menuitem_file_recent_items = gtk_recent_chooser_menu_new();
	recent_filter = gtk_recent_filter_new();
    //gtk_recent_filter_add_application(recent_filter, g_get_application_name());
    gtk_recent_filter_add_mime_type(recent_filter, "video/*");
    gtk_recent_filter_add_mime_type(recent_filter, "audio/*");
    gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);	
	gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
    gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
                                     GTK_RECENT_SORT_MRU);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_file_open_recent), menuitem_file_recent_items);
    gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
	g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
                     G_CALLBACK(menuitem_open_recent_item_activated), NULL);

	icon_theme = gtk_icon_theme_get_default();
    icon_list = NULL;
    if (gtk_icon_theme_has_icon(icon_theme, "fosfor")) {
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 128, 0, &error);
		if (error)
			printf("error %s\n",error->message);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 64, 0, NULL);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 48, 0, NULL);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 24, 0, NULL);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 22, 0, NULL);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
        pb_icon = gtk_icon_theme_load_icon(icon_theme, "fosfor", 16, 0, NULL);
        if (pb_icon)
            icon_list = g_list_prepend(icon_list, pb_icon);
	}
	gtk_window_set_default_icon_list(icon_list);
    gtk_window_set_icon_list(GTK_WINDOW(window), icon_list);

	
    g_timeout_add_seconds(1, update_gui, NULL);    
    g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
	gtk_widget_set_sensitive(menuitem_view, FALSE);
	if (embed_window)
		gtk_widget_hide(main_menu);
	
    clutter = gtk_clutter_embed_new();
	g_signal_connect(window,"enter-notify-event", G_CALLBACK(on_fixed_enter_notify_event), NULL);
	g_signal_connect(window,"leave-notify-event", G_CALLBACK(on_fixed_leave_notify_event), NULL);
	g_signal_connect(window, "scroll-event", G_CALLBACK(on_window_scroll_event), NULL);

	
    stage = gtk_clutter_embed_get_stage(GTK_CLUTTER_EMBED(clutter));
	
    clutter_stage_set_color(CLUTTER_STAGE(stage), &stage_color);

    media = clutter_gst_video_texture_new();
	clutter_actor_set_reactive(media, TRUE);

	pipeline = gst_element_factory_make("playbin2","pipeline");
	audio_sink = gst_element_factory_make("gconfaudiosink","audio-sink");
	if (!audio_sink) {
		audio_sink = gst_element_factory_make ("autoaudiosink", "audio-sink");
  		if (!audio_sink) {
			audio_sink = gst_element_factory_make ("alsasink", "audio-sink");
			g_warning ("Could not create a GST audio_sink. Audio unavailable.");
		}
    }

	video_sink = clutter_gst_video_sink_new(CLUTTER_TEXTURE(media));
	g_object_set (G_OBJECT (video_sink), "qos", TRUE, "sync", TRUE, NULL);
	g_object_set (G_OBJECT (pipeline),"video-sink", video_sink,"audio-sink", audio_sink,	NULL);

    g_signal_connect (pipeline, "notify::stream-info",G_CALLBACK (stream_info_notify_callback), NULL);
	g_signal_connect (pipeline, "element-added", G_CALLBACK (video_sink_element_added), NULL);   
    g_signal_connect (pipeline, "notify::stream-changed",G_CALLBACK (element_changed_callback), NULL);

	// when clutter-gst changes to playbin2, use these
	g_signal_connect (pipeline, "audio-changed", G_CALLBACK (element_changed_callback), NULL);   
	g_signal_connect (pipeline, "video-changed", G_CALLBACK (element_changed_callback), NULL);   
	g_signal_connect (pipeline, "text-changed", G_CALLBACK (element_changed_callback), NULL);   
	g_signal_connect (pipeline, "audio-tags-changed", G_CALLBACK (audio_tags_changed_callback), NULL);   
	g_signal_connect (pipeline, "text-tags-changed", G_CALLBACK (text_tags_changed_callback), NULL);   

    bus = gst_element_get_bus(pipeline);
	gst_bus_add_signal_watch(bus);
    g_signal_connect (bus, "message", G_CALLBACK(bus_message_callback),NULL);
	gst_object_unref(GST_OBJECT(bus));
	
    clutter_actor_set_position(media, 0,0);

    gtk_fixed_put(fixed,clutter,0,0);    
    gtk_widget_realize(window);
    
    clutter_actor_show(media);
    clutter_container_add_actor(CLUTTER_CONTAINER(stage),media);
	gtk_widget_show(GTK_WIDGET(clutter));
	gtk_widget_show(GTK_WIDGET(fixed));
	
	/* This is important */
	gtk_builder_connect_signals (builder, NULL);

	g_object_unref (builder);

	control_layout = clutter_box_layout_new();
	control_cbox = clutter_box_new(control_layout);
	clutter_box_layout_set_pack_start(CLUTTER_BOX_LAYOUT(control_layout), FALSE);
	
	crewind = fosfor_button_new_from_stock(GTK_STOCK_MEDIA_REWIND, GTK_ICON_SIZE_MENU);
	clutter_actor_show(crewind);
	g_signal_connect(G_OBJECT(crewind), "clicked", G_CALLBACK(on_rewind_clicked),NULL);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),crewind,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_CENTER);
	
	cplay_pause = fosfor_button_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
	clutter_actor_show(cplay_pause);
	clutter_actor_set_size(cplay_pause,clutter_actor_get_width(cplay_pause) * 1.5 , clutter_actor_get_height(cplay_pause));
	g_signal_connect(G_OBJECT(cplay_pause), "clicked", G_CALLBACK(on_play_pause_clicked),NULL);
	g_signal_connect(G_OBJECT(media), "button-release-event", G_CALLBACK(on_button_release_event),NULL);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),cplay_pause,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_CENTER);

	cstop = fosfor_button_new_from_stock(GTK_STOCK_MEDIA_STOP, GTK_ICON_SIZE_MENU);
	clutter_actor_show(cstop);
	g_signal_connect(G_OBJECT(cstop), "clicked", G_CALLBACK(on_stop_clicked),NULL);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),cstop,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_CENTER);
	
	cforward = fosfor_button_new_from_stock(GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU);
	clutter_actor_show(cforward);
	g_signal_connect(G_OBJECT(cforward), "clicked", G_CALLBACK(on_forward_clicked),NULL);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),cforward,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_CENTER);

	ctracker = fosfor_tracker_new();
	g_signal_connect (ctracker, "percentage-changed", G_CALLBACK (on_tracker_percentage_changed), NULL);  
	clutter_actor_show(ctracker);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),ctracker,TRUE,TRUE,TRUE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_CENTER);

	cvolume = fosfor_volume_new(GTK_ICON_SIZE_MENU);
	clutter_actor_show(cvolume);

	value = gst_stream_volume_get_volume (GST_STREAM_VOLUME (pipeline),
						                          GST_STREAM_VOLUME_FORMAT_CUBIC);
	printf ("volume = %f\n", value);
	value = CLAMP(value, 0.0, 1.0);
	
	fosfor_volume_set_value(FOSFOR_VOLUME(cvolume),value);

	g_signal_connect(G_OBJECT(cvolume), "percentage-changed", G_CALLBACK(on_volume_percentage_changed),NULL);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),cvolume,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_END,CLUTTER_BOX_ALIGNMENT_CENTER);

	
	cfullscreen = fosfor_button_new_from_stock(GTK_STOCK_FULLSCREEN, GTK_ICON_SIZE_MENU);
	fosfor_button_set_sensitive(FOSFOR_BUTTON(cfullscreen), FALSE);
	g_signal_connect(G_OBJECT(cfullscreen), "clicked", G_CALLBACK(on_fullscreen_clicked),NULL);
	
	clutter_actor_show(cfullscreen);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(control_layout),cfullscreen,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_END,CLUTTER_BOX_ALIGNMENT_CENTER);

	clutter_actor_set_size(control_cbox, clutter_actor_get_width(stage), clutter_actor_get_height(cplay_pause));

	control_background = clutter_cairo_texture_new(10,10);

	control_group = clutter_group_new();
	g_signal_connect(G_OBJECT(control_group), "paint", G_CALLBACK(on_control_group_paint),NULL);
	clutter_actor_set_opacity(control_group, 0xcc);
	clutter_container_add(CLUTTER_CONTAINER(control_group),control_background, control_cbox, NULL);
    clutter_container_add_actor(CLUTTER_CONTAINER(stage),CLUTTER_ACTOR(control_group));
	if (!idledata->showcontrols)
		clutter_actor_set_opacity(control_group, 0x00);
	
	return window;
}


int
main (int argc, char *argv[])
{
 	GtkWidget *window;
    GFile *file;
    gchar *uri, *basename, *title;
	GOptionContext *context;
	GError *error = NULL;
	GdkWindow *window_container = NULL;

	g_thread_init(NULL);
	gtk_init(&argc, &argv);
	clutter_threads_init();
	gtk_clutter_init(&argc, &argv);
    clutter_gst_init(&argc, &argv);
	
#ifdef ENABLE_NLS
	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);
#endif

	g_type_init();
	gtk_set_locale ();

	showcontrols = TRUE;
	disable_context_menu = FALSE;
	window_width = 0;
	window_height = 0;
	last_movement_time = 0;
	menu_update_mutex = g_mutex_new();
	
    context = g_option_context_new(_("[FILES...] - Media player using Clutter and GStreamer"));
    g_option_context_set_translation_domain(context, "UTF-8");
    g_option_context_set_translate_func(context, (GTranslateFunc) gettext, NULL, NULL);
    g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE);
    g_option_context_add_group(context, gtk_get_option_group(TRUE));
    g_option_context_parse(context, &argc, &argv, &error);
    g_option_context_free(context);
	

	g_set_application_name(_("Fosfor"));
	gtk_window_set_default_icon_name("fosfor");
	g_setenv("PULSE_PROP_media.role", "video", TRUE);
	
	isfullscreen = FALSE;
	verbose = 1;
	rpconsole = g_strdup("NONE");
	plugin_cache_size = 2048;
	idledata = (IdleData *) g_new0(IdleData, 1);
	idledata->showcontrols = showcontrols;
	playlist = NULL;
	currentitem = NULL;
	has_navigation = FALSE;
	
	window = create_window (embed_window);
	dbus_hookup(embed_window,control_id);

	if (embed_window) {
        while (gtk_events_pending())
            gtk_main_iteration();

        window_container = gdk_window_foreign_new(embed_window);
        if (GTK_WIDGET_MAPPED(window))
            gtk_widget_unmap(window);

        gdk_window_reparent(window->window, window_container, 0, 0);

	}

	gtk_widget_show_all(window);
	
	file = NULL;
    uri = NULL;
    if (argv[1])
	    file = g_file_new_for_commandline_arg(argv[1]);
    if (file != NULL) {
        uri = g_file_get_uri(file);
        g_object_unref(file);
    }

	gtk_widget_set_size_request(GTK_WIDGET(fixed),320,120);

	if (uri) {
		printf("playing %s \n",uri);
		fosfor_tracker_set_message(FOSFOR_TRACKER(ctracker),_("Playing"));
		add_item_to_playlist(uri);
		g_object_set(G_OBJECT(pipeline),"uri",uri,NULL);
		gst_element_set_state(pipeline, GST_STATE_PLAYING);
		
		file = g_file_new_for_uri(uri);
		basename = g_file_get_basename(file);
		g_object_unref(file);
		title = g_strdup_printf(_("%s - Fosfor"), basename);
		gtk_window_set_title(GTK_WINDOW(window),title);
		g_free(title);
		g_free(basename);
		g_free(uri);
		fosfor_button_set_from_stock(FOSFOR_BUTTON(cplay_pause), GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU);
	} else {
		fosfor_button_set_from_stock(FOSFOR_BUTTON(cplay_pause), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
	}
	
	if (embed_window)
		gtk_widget_hide(main_menu);		


	gtk_main();
	return 0;
}
